/*********************************************************************
 *
 * Copyright (C) 2013 Bert Havinga
 * Inspired by the Railuino idea of Joerg Pleumann
 *
 * This example is free software; you can redistribute it and/or
 * modify it under the terms of the Creative Commons Zero License,
 * version 1.0, as published by the Creative Commons Organisation.
 * This effectively puts the file into the public domain.
 *
 * This example is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * LICENSE file for more details.
 */

#include <Railuino.h>

const word WAIT = 10; // 100 = 0,1 second
const word bus =0; //s88 bus 0 
char sbuffer[13];
int index;
byte mSize;
boolean sketchDebug = false;
boolean rptrEventEna = false;

TrackReporterS88 rptr(false); // Init the arduino, param is debugmode
TrackMessage message;

void setup() {
  digitalWrite(LED, LOW);
  Serial.begin(500000);
  while (!Serial);
  mSize=rptr.ProbeBus(0); // Init and detect nr of attached reporters
  Serial.setTimeout(20);
  digitalWrite(LED, HIGH);

}

void checkDiff() {
  boolean diffdetected = false;
  unsigned char contacts = 0;
  int bitnr;
  // check for difference between Readbuffer and ReadHistoryBuffer
    for (int i = 0; i < mSize*2 ; i++) {
    contacts = rptr.getDecoder(i) & ~(rptr.getPrevDecoder(i)); // contact set
    contacts |= rptr.getPrevDecoder(i) & ~(rptr.getDecoder(i)); // contact reset
    if (sketchDebug) {
      Serial.print("contact difference 'contacts': ");
      Serial.println(contacts, HEX);
    }
    if (contacts != 0) {
      diffdetected=true ;
      if (sketchDebug) {
        Serial.println("diffdetected=true");
      }
      for (bitnr=0; bitnr<8 ; bitnr++) {
        if (sketchDebug) {
          Serial.print("bit for this datagram: ");
          Serial.println((contacts & bit(bitnr)), HEX);
        }
        if ((contacts & bit(bitnr)) != 0) { //every change should generate a datagram 
          if (sketchDebug) {
            Serial.print("array position: ");
            Serial.println(i, HEX);
          }
          int s88nr = i;
          s88nr++;
          // compute nr of pairs
          int modulo = s88nr % 2;
          if (modulo = 1) {
            s88nr++;  //create even number for division
          }
          s88nr = s88nr / 2;
          if (sketchDebug) {
            Serial.print("16bit rep nr: ");
            Serial.println(s88nr, HEX);
          }
          message.hash = 0xdf34;
          message.command = 0x11;
          message.response = 0;
          message.length = 8;
          message.data[0] = 'R';
          message.data[1] = 'c';
          // compute kontaktkennung
          word kk = i*8;
          kk = kk + bitnr;
          message.data[2] = highByte(kk);
          message.data[3] = lowByte(kk);
          message.data[4] = rptr.getPrevDecoder(i);
          message.data[5] = rptr.getDecoder(i);
          message.data[6] = 0;
          message.data[7] = 0;
          message.sendmessage();
          // while(1) {} // stop here for a single run during debug 
        } 
      }	
    }
  }
}


void fillmsgheader() {
  message.response = true;
  message.hash = 0xdf34;
  message.data[0] = 'R';
  message.data[1] = 'c';
}  

void reporterPolling(int nr_reporters) {
  if (message.length == 5) {
    fillmsgheader();
    index =0;
    message.length = 7;
    message.data[2] = 'R';
    message.data[3] = 'l';
    message.data[7] = 0;
    if (sketchDebug == true) {
      Serial.println("polling request received");
    }
    Serial.print("poll req rcvd");
    if (rptrEventEna == false) {
      if (sketchDebug == true) {
        Serial.println("rptrEventEna = disabled, starting a refresh;");
      }  
      rptr.refresh();
    }
    for (int i=0; i <= nr_reporters; i++) {
      message.data[4] = i;
      message.data[6] = rptr.getDecoder(index);
      index++;
      message.data[5] = rptr.getDecoder(index);
      index++;
      message.sendmessage();
    }
  }
}

void EventEna() {
  byte mask;
  word reqbus;
  word reqcontact;
  int contactbit;
  rptrEventEna = true; // set eventhandler in loop
  //  Serial.print("rptrEventEnab");
  switch (message.length) {
  case 4:
    {  
      reqbus = (message.data[0] << 8);
      reqbus |= message.data[1];
      if (reqbus == bus) {
        fillmsgheader();
        //compute requested switch nr
        reqcontact = (message.data[2] << 8);
        reqcontact |= message.data[3];
        message.data[4] = rptr.getprevValue(reqcontact);
        message.data[5] = rptr.getValue(reqcontact);
        message.data[6] = 0; // time not implemented
        message.data[7] = 0;
        message.length = 8;
        message.sendmessage();
      }
    }
  case 5:
    {
      reqbus = (message.data[0] << 8);
      reqbus |= message.data[1];
      if (reqbus == bus) {
        fillmsgheader();
        //compute requested switch nr for events
        reqcontact = (message.data[2] << 8);
        reqcontact |= message.data[3];
        if (message.data[4]) 
        {
          rptr.setEventSwitches(reqcontact);
        }
        else
        {
          rptr.clrEventSwitches(reqcontact);
        }
        message.data[4] = rptr.getprevValue(reqcontact);
        message.data[5] = rptr.getValue(reqcontact);
        message.data[7] = 0; // time not implemented
        message.data[8] = 0;
        message.length = 8;
        if (sketchDebug) {
          message.printmessage();		
        }
        message.sendmessage();
      }
    }  
  case 7: 
    { //enables all switches for events
      rptr.setEventReporters(message.data[4]);
      fillmsgheader();
      message.data[7] = 0; // time not implemented
      message.data[8] = 0;
      message.length = 8;
      message.sendmessage();
      if (sketchDebug) {
        Serial.println("eventEna for all reporters switches");
        message.printmessage();		
      }
    }  
  }
}

void loop() {
  if (Serial.available()) {  // waiting for a serial CAN bus message
    if (Serial.readBytes(sbuffer, 13) == 13) {
      message.clear();
      message.command = (sbuffer[0] << 7);  // shift prio and command msbit
      message.response = (sbuffer[1] & 0x01);
      message.command |= ((sbuffer[1] & 0xFE) >> 1);
      message.hash = (sbuffer[2] << 8);
      message.hash |= sbuffer[3];
      message.length = sbuffer[4];
      for (int i=0; i < 9; i++) {
        message.data[i] = sbuffer[i+5];
      }
      message.sendmessage();
      if (sketchDebug == true) {
        Serial.println("incoming msg:");
        message.printmessage();		
      }

      if (message.hash == 0x0300) {
        switch (message.command) {
        case 0x10: 
          reporterPolling(message.data[4]);
        case 0x11: 
          EventEna();  

        }
      }
    } 
  }
  if (rptrEventEna == true) {
    rptr.refresh();
    checkDiff();
  }
  if (sketchDebug) {
    Serial.print("rptrEventEna status: ");
    Serial.println(rptrEventEna);
  }
  delay(WAIT);  // delay mag blijkbaar niet als laatste inde lus staan
  //  Serial.println("new loop");
  //    while(1) { } //stop the loop
}




